/*
 * The manager initializes and controls the network.
 */
package simulator.network;

import java.sql.*;
import java.util.*;
import java.util.logging.*;

/**
 *
 * @author Pascal Schwenke <pascal.schwenke@gmail.com>
 */
public class Manager {
    //Database strings

    String url = "jdbc:mysql://localhost:3306/test";
    String user = "root";
    String password = "SNET4ever";
    String dayTime = "Morning";
    Network network;
    //Global attributes used to query for transition rules in db
    String day;
    String hour;
    //TODO: add DB connection for getting rules

    public Manager() throws Exception {
        day = Integer.toString(Calendar.getInstance().get(Calendar.DAY_OF_WEEK));
        hour = Integer.toString(Calendar.getInstance().get(Calendar.HOUR_OF_DAY));
        //TODO: implement time correctly
        hour = "6";
//TODO: Sollte nicht in den Constuctor
        String query = "SELECT * FROM simple10x10new";
        Connection connect;
        Statement statement;
        ResultSet resultSet;

        // This will load the MySQL driver, each DB has its own driver
        Class.forName("com.mysql.jdbc.Driver");
        // Setup the connection with the DB
        connect = DriverManager
                .getConnection(url, user, password);
        statement = connect.createStatement();
        resultSet = statement.executeQuery(query);

        try {
            network = new Network();

            network.InitializeFromDB(resultSet);
        } catch (Exception ex) {
            Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void SetNetwork(Network n) {
        network = n;
    }

    //TODO: Remove this and implement time correctly
    private String TimeHelper() {
        return hour;
    }

    public Network SimulationStep() throws Exception {
        String rulesTable = "transitionrules";
        Connection connect;
        Statement statement;
        ResultSet resultSet;
        // This will load the MySQL driver, each DB has its own driver
        Class.forName("com.mysql.jdbc.Driver");
        // Setup the connection with the DB
        connect = DriverManager
                .getConnection(url, user, password);
        statement = connect.createStatement();
        //TODO: parallelisieren
        Network nextNetwork = network.EmptyNetwork();
        for (int i = 0; i < network.cells.size(); i++) {//for every cell
            String cellId = "";
            float toNeighbor;
            float lost = 0f;
            for (int j = 0; j < network.cells.get(i).neighbors.length; j++) {//process every transition
                cellId = network.cells.get(i).neighbors[j];
                //get transition rule for the neighbor
                String query = "SELECT percent FROM " + rulesTable + " WHERE fromCell=" + network.cells.get(i).id
                        + " AND toCell=" + cellId + " AND timeStart=" + hour + " AND weekDay=" + day + ";";
                resultSet = statement.executeQuery(query);
                //apply transition rule to the user count and add the result in the empty network
                //TODO: implement dealing with several results
                if (resultSet.next()) {
                    toNeighbor = network.cells.get(i).userCount / 100.0f * resultSet.getFloat("percent");
                    lost += toNeighbor;
                    nextNetwork.GetCellById(Integer.parseInt(cellId)).userCount += toNeighbor;
                }
            }
            nextNetwork.GetCellById(network.cells.get(i).id).userCount += network.cells.get(i).userCount - lost;
        }
        return nextNetwork;
    }

    public Network GetNetwork() {
        return network;
    }

    public void ChangeHour(int diff) {
        int newHour = Integer.parseInt(hour) + diff;
        if (newHour < 0) {
            newHour = 23;
        } else if (newHour > 23) {
            newHour = 0;
        }
        hour = Integer.toString(newHour);
    }

    public void ChangeDay(int diff) {
        int newDay = Integer.parseInt(day) + diff;
        if (newDay < 1) {
            newDay = 7;
        } else if (newDay > 7) {
            newDay = 1;
        }
        day = Integer.toString(newDay);
    }

    public void CreateRules(int time) throws Exception {
        Connection connect;
        PreparedStatement statement;
        ResultSet resultSet;

        String query = "UPDATE transitionrules SET percent=? WHERE fromCell=? AND toCell=? AND timeStart=?;";
        // This will load the MySQL driver, each DB has its own driver
        Class.forName("com.mysql.jdbc.Driver");
        // Setup the connection with the DB
        connect = DriverManager
                .getConnection(url, user, password);
        connect.setAutoCommit(false);
        statement = connect.prepareStatement(query);
        for (int i = 0; i < network.cells.size(); i++) {//for each cell
            for (int j = 0; j < network.cells.get(i).neighbors.length; j++) {//for each neighbor
                String from = network.cells.get(i).type;
                String to = network.GetCellById(Integer.parseInt(network.cells.get(i).neighbors[j])).type;
                String per = Integer.toString(GetTransitionWeight(to, from));
                statement.setString(1, per);
                statement.setString(2, Integer.toString(network.cells.get(i).id));
                statement.setString(3, network.cells.get(i).neighbors[j]);
                statement.setString(4, Integer.toString(time));
                statement.executeUpdate();
            }
        }
        connect.commit();
    }

    private int GetTransitionWeight(String from, String to) {
        if ("city".equals(from) && "city".equals(to)) {
            return 10;
        }
        if ("city".equals(from) && "forest".equals(to)) {
            return 0;
        }
        if ("city".equals(from) && "highway".equals(to)) {
            return 4;
        }
        if ("city".equals(from) && "town".equals(to)) {
            return 0;
        }

        if ("forest".equals(from) && "city".equals(to)) {
            return 0;
        }
        if ("forest".equals(from) && "forest".equals(to)) {
            return 0;
        }
        if ("forest".equals(from) && "highway".equals(to)) {
            return 0;
        }
        if ("forest".equals(from) && "town".equals(to)) {
            return 0;
        }

        if ("town".equals(from) && "city".equals(to)) {
            return 0;
        }
        if ("town".equals(from) && "forest".equals(to)) {
            return 0;
        }
        if ("town".equals(from) && "highway".equals(to)) {
            return 15;
        }
        if ("town".equals(from) && "town".equals(to)) {
            return 20;
        }

        if ("highway".equals(from) && "city".equals(to)) {
            return 15;
        }
        if ("highway".equals(from) && "forest".equals(to)) {
            return 0;
        }
        if ("highway".equals(from) && "highway".equals(to)) {
            return 22;
        }
        if ("highway".equals(from) && "town".equals(to)) {
            return 4;
        }
        return 0;
    }

    public String GetDayTime() {
        return dayTime;
    }

    public void ChangeDayTime() {
        if ("6".equals(hour)) {
            dayTime = "Midday";
            hour = "13";
        } else {
            hour = "6";
            dayTime = "morning";
        }
    }
}
